home *** CD-ROM | disk | FTP | other *** search
- #define LIBQBUILD_CORE
- #include "../include/libqbuild.h"
-
- bool mergedebug; // ?
-
- /*
- * ================
- * CheckColinear
- *
- * ================
- */
- void CheckColinear(register struct visfacet * f)
- {
- int i, j;
- vec3_t v1, v2;
-
- for (i = 0; i < f->numpoints; i++) {
- // skip the point if the vector from the previous point is the same
- // as the vector to the next point
- j = (i - 1 < 0) ? f->numpoints - 1 : i - 1;
- VectorSubtract(f->pts[i], f->pts[j], v1);
- VectorNormalize(v1);
-
- j = (i + 1 == f->numpoints) ? 0 : i + 1;
- VectorSubtract(f->pts[j], f->pts[i], v2);
- VectorNormalize(v2);
-
- if (VectorCompare(v1, v2))
- Error("Colinear edge");
- }
-
- }
-
- /*
- * =============
- * TryMerge
- *
- * If two polygons share a common edge and the edges that meet at the
- * common points are both inside the other polygons, merge them
- *
- * Returns NULL if the faces couldn't be merged, or the new face.
- * The originals will NOT be freed.
- * =============
- */
- struct visfacet *TryMerge(__memBase, register struct visfacet * f1, register struct visfacet * f2)
- {
- vec_t *p1, *p2, *p3, *p4, *back;
- struct visfacet *newf;
- int i, j, k, l;
- vec3_t normal, delta, planenormal;
- vec_t dot;
- struct plane *plane;
- bool keep1, keep2;
-
- if (f1->numpoints == -1 || f2->numpoints == -1)
- return NULL;
- if (f1->planeside != f2->planeside)
- return NULL;
- if (f1->texturenum != f2->texturenum)
- return NULL;
- if (f1->contents[0] != f2->contents[0])
- return NULL;
- if (f1->contents[1] != f2->contents[1])
- return NULL;
-
- //
- // find a common edge
- //
- p1 = p2 = NULL; // stop compiler warning
-
- j = 0; //
-
- for (i = 0; i < f1->numpoints; i++) {
- p1 = f1->pts[i];
- p2 = f1->pts[(i + 1) % f1->numpoints];
- for (j = 0; j < f2->numpoints; j++) {
- p3 = f2->pts[j];
- p4 = f2->pts[(j + 1) % f2->numpoints];
- for (k = 0; k < 3; k++) {
- if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
- break;
- if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
- break;
- }
- if (k == 3)
- break;
- }
- if (j < f2->numpoints)
- break;
- }
-
- if (i == f1->numpoints)
- return NULL; // no matching edges
-
- //
- // check slope of connected lines
- // if the slopes are colinear, the point can be removed
- //
- #ifdef EXHAUSIVE_CHECK
- if(f1->planenum >= bspMem->numbrushplanes || f1->planenum < 0)
- Error("looking for nonexisting plane %d\n", f1->planenum);
- #endif
- plane = &bspMem->brushplanes[f1->planenum];
- VectorCopy(plane->normal, planenormal);
- if (f1->planeside)
- VectorNegate(planenormal);
-
- back = f1->pts[(i + f1->numpoints - 1) % f1->numpoints];
- VectorSubtract(p1, back, delta);
- CrossProduct(planenormal, delta, normal);
- VectorNormalize(normal);
-
- back = f2->pts[(j + 2) % f2->numpoints];
- VectorSubtract(back, p1, delta);
- dot = DotProduct(delta, normal);
- if (dot > CONTINUOUS_EPSILON)
- return NULL; // not a convex polygon
-
- keep1 = dot < -CONTINUOUS_EPSILON;
-
- back = f1->pts[(i + 2) % f1->numpoints];
- VectorSubtract(back, p2, delta);
- CrossProduct(planenormal, delta, normal);
- VectorNormalize(normal);
-
- back = f2->pts[(j + f2->numpoints - 1) % f2->numpoints];
- VectorSubtract(back, p2, delta);
- dot = DotProduct(delta, normal);
- if (dot > CONTINUOUS_EPSILON)
- return NULL; // not a convex polygon
-
- keep2 = dot < -CONTINUOUS_EPSILON;
-
- //
- // build the new polygon
- //
- if (f1->numpoints + f2->numpoints > MAXEDGES) {
- // Error ("TryMerge: too many edges!");
- return NULL;
- }
-
- newf = NewFaceFromFace(f1, MAXEDGES);
-
- // copy first polygon
- for (k = (i + 1) % f1->numpoints; k != i; k = (k + 1) % f1->numpoints) {
- if (k == (i + 1) % f1->numpoints && !keep2)
- continue;
-
- VectorCopy(f1->pts[k], newf->pts[newf->numpoints]);
- newf->numpoints++;
- }
-
- // copy second polygon
- for (l = (j + 1) % f2->numpoints; l != j; l = (l + 1) % f2->numpoints) {
- if (l == (j + 1) % f2->numpoints && !keep1)
- continue;
- VectorCopy(f2->pts[l], newf->pts[newf->numpoints]);
- newf->numpoints++;
- }
-
- RecalcFace(newf);
- // mprintf("TryMerge: merged %d + %d to %d\n", f1->numpoints, f2->numpoints, newf->numpoints);
-
- return newf;
- }
-
- /*
- * ===============
- * MergeFaceToList
- * ===============
- */
- struct visfacet *MergeFaceToList(__memBase, struct visfacet * face, struct visfacet * list)
- {
- struct visfacet *newf, *f;
-
- for (f = list; f; f = f->next) {
- //CheckColinear (f);
- if (mergedebug) {
- Draw_ClearWindow();
- Draw_DrawFace(face);
- Draw_DrawFace(f);
- Draw_SetBlack();
- }
- newf = TryMerge(bspMem, face, f);
- if (!newf)
- continue;
- FreeFace(face);
- f->numpoints = -1; // merged out
-
- return MergeFaceToList(bspMem, newf, list);
- }
-
- // didn't merge, so add at start
- face->next = list;
- return face;
- }
-
- /*
- * ===============
- * FreeMergeListScraps
- * ===============
- */
- struct visfacet *FreeMergeListScraps(struct visfacet * merged)
- {
- struct visfacet *head, *next;
-
- head = NULL;
- for (; merged; merged = next) {
- next = merged->next;
- if (merged->numpoints == -1)
- FreeFace(merged);
- else {
- merged->next = head;
- head = merged;
- }
- }
-
- return head;
- }
-
- /*
- * ===============
- * MergePlaneFaces
- * ===============
- */
- void MergePlaneFaces(__memBase, struct surface * plane)
- {
- struct visfacet *f1, *next;
- struct visfacet *merged;
-
- merged = NULL;
-
- for (f1 = plane->faces; f1; f1 = next) {
- next = f1->next;
- merged = MergeFaceToList(bspMem, f1, merged);
- }
-
- // chain all of the non-empty faces to the plane
- plane->faces = FreeMergeListScraps(merged);
- }
-
- /*
- * ============
- * MergeAll
- * ============
- */
- void MergeAll(__memBase, struct surface * surfhead)
- {
- struct surface *surf;
- int mergefaces, numsurf = 0, i;
- struct visfacet *f;
-
- mprintf("----- MergeAll ----------\n");
-
- /* PROGRESS-ONLY! */
- for (surf = surfhead; surf; surf = surf->next)
- numsurf++;
-
- mergefaces = 0;
- for (surf = surfhead, i = 0; surf; surf = surf->next, i++) {
- MergePlaneFaces(bspMem, surf);
- Draw_ClearWindow();
- for (f = surf->faces; f; f = f->next) {
- Draw_DrawFace(f);
- mergefaces++;
- }
- mprogress(numsurf, i + 1);
- }
-
- mprintf("%5i mergefaces\n", mergefaces);
- }
-